package org.maxgroundstation.simulation.service.wifi;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Iterator;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.maxgroundstation.simulation.MaxRobot;
import org.maxgroundstation.simulation.service.Service;
import org.maxgroundstation.simulation.service.ServiceCommunication;
import org.maxgroundstation.simulation.service.ServiceDataFrame;
import org.maxgroundstation.simulation.service.ServiceSubscriber;
import org.maxgroundstation.simulation.service.ServiceUtil;

/**
 * The WiFi signal strength service.
 */
public class WiFiService extends Service {

    // Static members
    public static final String SERVICE_ID = ServiceUtil.getServiceID("wifi_ss");
    public static final long SLEEP_TIME = 500L;
    
    // Data members
    private ScheduledThreadPoolExecutor executor;
    
    /**
     * Constructor
     * @param comm the service communication.
     */
    public WiFiService(ServiceCommunication comm) {
        // Use Service constructor.
        super(comm);
        
        name = "WiFi Signal Strength";
        description = "Displays the rover's WiFi signal strength.";
        
        // Start update thread execution.
        startExecution();
    }
    
    /**
     * Starts executing the wifi updates.
     */
    private void startExecution() {
        if (executor != null) executor.shutdownNow();
        
        executor = new ScheduledThreadPoolExecutor(1);
        executor.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                // Update WiFi signal strength.
                MaxRobot robot = getServiceCommunication().getRobot();
                float wifiStrength = robot.getWiFiSignalStrength();
                
                try {
                    sendWiFiSignalStrength(wifiStrength);
                }
                catch (Exception e) {
                    comm.log(e);
                }
            }       
        }, 0, SLEEP_TIME, TimeUnit.MILLISECONDS);
    }
    
    /**
     * Sends the WiFi signal strength to service subscribers.
     * @param wifiStrength the WiFi signal strength (percentage).
     * @throws Exception if error sending WiFi signal strength.
     */
    private void sendWiFiSignalStrength(float wifiStrength) throws Exception {
        
        // Get wifiStrength as an array of bytes.
        ByteBuffer buff = ByteBuffer.allocate(4);
        buff.order(ByteOrder.LITTLE_ENDIAN);
        buff.putFloat(wifiStrength);
        byte[] wifiStrengthData = buff.array();
        
        Iterator<ServiceSubscriber> i = subscribers.iterator();
        while (i.hasNext()) {
            ServiceSubscriber subscriber = i.next();
            if (comm.getClientManager().checkClient(subscriber.getClientID())) {
                try {
                    //System.out.println("Sending WiFi signal strength: " + wifiStrength);
                    comm.sendServicePost(subscriber.getCommType(), getID(), 
                            subscriber.getClientID(), wifiStrengthData);
                }
                catch (Exception e) {
                    //e.printStackTrace(System.err);
                    comm.log(e);
                }
            }
            else i.remove();
        }
    }
    
    @Override
    public String getID() {
        return SERVICE_ID;
    }

    @Override
    public void handleResponse(ServiceDataFrame dataFrame, int commType) throws Exception {
        // Do nothing.
    }

    @Override
    public boolean isDefaultService() {
        return false;
    }

    @Override
    public boolean isSubscribable() {
        return true;
    }

    @Override
    public void shutDown() {
        executor.shutdownNow();
    }
}